package com.dc.docs._888_面试.concurrent._4_lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Description: 自定义自旋锁
 * @author: gdc
 * @date: 2021/6/16
 * @version 1.0
 */
public class SpinLock {

    /**
     * 原子引用线程
     */
    private AtomicReference<Thread> atomicReference = new AtomicReference<>();

    /**
     * 加锁，自旋实现
     */
    public void lock(){
        Thread thread = Thread.currentThread();
        // 当atomicReference存放的线程不为空时，该循环会一直持续
        // 存放的线程为空，会添加新的线程，并满足条件跳出循环
        while (!atomicReference.compareAndSet(null, thread)){

        }
        System.out.println(thread.getName() + ", come in");
    }

    /**
     * 解锁
     */
    public void unlock(){
        Thread thread = Thread.currentThread();

        // 当 atomicReference存放的线程不为空时，将线程置为空，完成解锁
        boolean result = atomicReference.compareAndSet(thread, null);
        if (result) {
            System.out.println(thread.getName() + ", invoked unlock");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        SpinLock spinLock = new SpinLock();
        new Thread(() -> {
            spinLock.lock();

            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            spinLock.unlock();
        }, "AA").start();

        TimeUnit.SECONDS.sleep(1);

        new Thread(() -> {
            spinLock.lock();

            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            spinLock.unlock();
        }, "BB").start();
    }
}
